package com.fjbdxk.beidou;


import com.fjbdxk.beidou.msg.BDFKIMessage;
import com.fjbdxk.beidou.msg.CCTCQMessage;
import com.fjbdxk.beidou.net.SocketBeiDouNet;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
 * 发送示例
 *
 * @author huanggy
 * @version 1.0.0
 * @date 2024/05/13
 **/
public class SendFileTest {


    private static final Logger LOGGER = Logger.getLogger(SendExample.class.getName());

    public static void main(String[] args) throws InterruptedException {
        // 使用网口通信
        SocketBeiDouNet socketBeiDouNet = new SocketBeiDouNet();
        socketBeiDouNet.open();//打开网络通信

        sendFile(socketBeiDouNet);


    }




    public static List<String> getFileData() {
        String csvFile = "D:\\工作日期\\20240514\\1.csv";//csv文件路径

        String line;
        String csvSplitBy = ",";// CSV文件中字段的分隔符

        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(csvFile), "GBK"))) {
            int i = 0;
            String[] head = new String[]{"PLC状态", "环境温度", "风速", "功率", "转矩", "发电机转速", "叶轮转速", "风向", "桨距角", "发电量"};//csv文件的列头
            List<String> res = new ArrayList<>();//存储处理后的数据
            while ((line = br.readLine()) != null) {// 逐行读取CSV文件内容
                String[] data = line.split(csvSplitBy);// 按照分隔符将一行数据拆分成数组
                //if(i>0){
                // 在这里处理每一行的数据
                String r = "";
                for (int j = 0; j < data.length; j++) {//遍历每个字段
                    String t1 = head[j];// 获取列头
                    String t2 = data[j];//获取字段值
                    switch (t1) {// 根据列头进行数据处理
                        case "PLC状态":
                            t2 = validateAndSendData(t1, t2, 1.0, 0, 70, 8);
                            break;
                        case "环境温度":
                            t2 = validateAndSendData(t1, t2, 1.0, -50, 50, 8);
                            break;
                        case "风速":
                            t2 = validateAndSendData(t1, t2, 0.01, 0, 10000, 16);
                            break;
                        case "功率":
                            t2 = validateAndSendData(t1, t2, 0.01, 0, 10000, 16);
                            break;
                        case "转矩":
                            t2 = validateAndSendData(t1, t2, 0.1, 0, 10000, 16);
                            break;
                        case "发电机转速":
                            t2 = validateAndSendData(t1, t2, 1.0, 0, 2000, 16);
                            break;
                        case "叶轮转速":
                            t2 = validateAndSendData(t1, t2, 0.01, 0, 2000, 16);
                            break;
                        case "风向":
                            t2 = validateAndSendData(t1, t2, 0.1, 0, 3600, 16);
                            break;
                        case "桨距角":
                            t2 = validateAndSendData(t1, t2, 0.1, -100, 1000, 16);
                            break;
                        case "发电量":
                            t2 = validateAndSendData(t1, t2, 1.0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 32);
                            break;
                        default:
                            LOGGER.warning("Unsupported point: " + t1);// 输出不支持的列头
                            break;
                    }
                    System.out.println("解析之后的值为：" + t2);
                    r += t2;
//                        if(j != data.length-1){
//                            r += ",";
//                        }

                }
                res.add(r);// 将处理后的数据添加到res列表中
                //}

                System.out.println();
                i++;
            }
            System.out.println(res);
            return res;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ArrayList<>();// 返回空列表
    }

    /**
     * 验证并发送数据
     *
     * @param pointName     数据点名称
     * @param pointValueStr 数据点值字符串
     * @param coefficient   系数
     * @param lowerBound    下限
     * @param upperBound    上限
     * @param position      位置
     * @return 处理后的数据点值字符串
     */
    private static String validateAndSendData(String pointName, String pointValueStr, double coefficient, double lowerBound, double upperBound, int position) {
        if (coefficient == 1.0) {
            // 如果系数为1.0
            // 调用int-short-byte方法处理数据点值
            pointValueStr = intshortbyte(pointName, pointValueStr, (int) coefficient, lowerBound, upperBound, position);
        }
        if (coefficient == 0.1) {
            // 如果系数为0.1
            // 调用double-int-short-byte方法处理数据点值
            pointValueStr = doubleintshortbyte(pointName, pointValueStr, coefficient, lowerBound, upperBound, position);
        }
        if (coefficient == 0.01) {
            // 如果系数为0.01
            // 调用float-int-shor-tbyte方法处理数据点值
            pointValueStr = floatintshortbyte(pointName, pointValueStr, (float) coefficient, lowerBound, upperBound, position);
        }
        // 返回处理后的数据点值字符串
        return pointValueStr;
    }


    /**
     * 处理float类型数据点值
     *
     * @param pointName     数据点名称
     * @param pointValueStr 数据点值字符串
     * @param coefficient   系数
     * @param lowerBound    下限
     * @param upperBound    上限
     * @param position      位置
     * @return 处理后的数据点值字符串
     */
    private static String floatintshortbyte(String pointName, String pointValueStr, float coefficient, double lowerBound, double upperBound, int position) {
        try {
            float value = Float.parseFloat(pointValueStr) / coefficient;  // 将数据点值字符串转换为float类型并根据系数进行转换
            LOGGER.info("Range for " + pointName + ": " + lowerBound + " to " + upperBound);  // 记录数据点范围信息
            if (value < lowerBound || value > upperBound) {  // 判断转换后的值是否在范围内
                LOGGER.warning("Value for " + pointName + " out of range: " + pointValueStr);  // 记录数值超出范围的警告信息
                pointValueStr = getTag(position);  // 获取标记值并赋给数据点值字符串
            } else {
                int intValue = (int) value;  // 将float值转换为int
                pointValueStr = inttobyte(intValue, position);  // 调用inttobyte方法处理int值并赋给数据点值字符串
            }
        } catch (NumberFormatException e) {
            LOGGER.warning("Invalid value for " + pointName + ": " + pointValueStr);  // 记录无效数值的警告信息
            pointValueStr = getTag(position);  // 获取标记值并赋给数据点值字符串
        }
        return pointValueStr;  // 返回处理后的数据点值字符串
    }


    /**
     * 获取标记字符串
     *
     * @param count 标记个数
     * @return 标记字符串
     */
    private static String getTag(int count) {
        StringBuilder sb = new StringBuilder();  // 创建StringBuilder对象
        for (int i = 0; i < count; i++) {  // 循环count次
            sb.append("#");  // 在StringBuilder中添加"#"
        }
        String hashString = sb.toString();  // 将StringBuilder转换为字符串
        return hashString;  // 返回标记字符串
    }


    /**
     * 处理double类型数据点值
     *
     * @param pointName     数据点名称
     * @param pointValueStr 数据点值字符串
     * @param coefficient   系数
     * @param lowerBound    下限
     * @param upperBound    上限
     * @param position      位置
     * @return 处理后的数据点值字符串
     */
    private static String doubleintshortbyte(String pointName, String pointValueStr, double coefficient, double lowerBound, double upperBound, int position) {
        try {
            double value = Double.parseDouble(pointValueStr) / coefficient;  // 将数据点值字符串转换为double类型并根据系数进行转换
            LOGGER.info("Range for " + pointName + ": " + lowerBound + " to " + upperBound);  // 记录数据点范围信息
            if (value < lowerBound || value > upperBound) {  // 判断转换后的值是否在范围内
                LOGGER.warning("Value for " + pointName + " out of range: " + pointValueStr);  // 记录数值超出范围的警告信息
                pointValueStr = getTag(position);  // 获取标记值并赋给数据点值字符串
            } else {
                //double doubleValue = 1234.5678;
                int intValue = (int) value;  // 将double值转换为int
                pointValueStr = inttobyte(intValue, position);  // 调用inttobyte方法处理int值并赋给数据点值字符串
            }
        } catch (NumberFormatException e) {
            LOGGER.warning("Invalid value for " + pointName + ": " + pointValueStr);  // 记录无效数值的警告信息
            pointValueStr = getTag(position);  // 获取标记值并赋给数据点值字符串
        }
        return pointValueStr;  // 返回处理后的数据点值字符串
    }


    /**
     * 处理int类型数据点值
     *
     * @param pointName     数据点名称
     * @param pointValueStr 数据点值字符串
     * @param coefficient   系数
     * @param lowerBound    下限
     * @param upperBound    上限
     * @param position      位置
     * @return 处理后的数据点值字符串
     */
    private static String intshortbyte(String pointName, String pointValueStr, int coefficient, double lowerBound, double upperBound, int position) {
        try {
            int value = Integer.parseInt(pointValueStr) / coefficient;  // 将数据点值字符串转换为int类型并根据系数进行转换
            LOGGER.info("Range for " + pointName + ": " + lowerBound + " to " + upperBound);  // 记录数据点范围信息
            if (value < lowerBound || value > upperBound) {  // 判断转换后的值是否在范围内
                LOGGER.warning("Value for " + pointName + " out of range: " + pointValueStr);  // 记录数值超出范围的警告信息
                pointValueStr = getTag(position);  // 获取标记值并赋给数据点值字符串
            } else {
                pointValueStr = inttobyte(value, position);  // 调用inttobyte方法处理int值并赋给数据点值字符串
            }
        } catch (NumberFormatException e) {
            LOGGER.warning("Invalid value for " + pointName + ": " + pointValueStr);  // 记录无效数值的警告信息
            pointValueStr = getTag(position);  // 获取标记值并赋给数据点值字符串
        }
        return pointValueStr;  // 返回处理后的数据点值字符串
    }



    /**
     * 将整数转换为字节串
     *
     * @param number   要转换的整数
     * @param position 二进制串的长度
     * @return 转换后的二进制字符串
     */
    public static String inttobyte(int number, int position) {
        //float->int-short-byte
        // 将整数转换为短整数
        int decimalNumber = number;
        short shortValue = (short) decimalNumber;
        // 将短整数转换为二进制字符串
        String binaryString = Integer.toBinaryString(shortValue);

        // Ensure the binary string is exactly 8 bits (1 byte) long
        // 确保二进制字符串的长度为position
        String paddedBinaryString = String.format("%" + position + "s", binaryString).replace(' ', '0');

        // Print the padded binary representation
        // 打印填充后的二进制表示
        System.out.println("Padded binary representation of " + decimalNumber + " is: " + paddedBinaryString);
        return paddedBinaryString;// 返回填充后的二进制字符串
    }



    /**
     * 发送文件数据到Socket贝斗网
     *
     * @param socketBeiDouNet Socket贝斗网对象
     * @throws InterruptedException 中断异常
     */
    public static void sendFile(SocketBeiDouNet socketBeiDouNet) throws InterruptedException {
        // 获取文件数据
        List<String> fileData = getFileData();
        // 遍历文件数据列表
        for (int i = 0; i < fileData.size(); i++) {
            // 打印分段发送的值
            System.out.println("分段发送的值为：" + fileData.get(i));
            // 创建CCTCQMessage对象
            CCTCQMessage msg = new CCTCQMessage(15950114, fileData.get(i));
            msg.setEncodeType(2);  // 设置编码类型
            System.out.println(msg.getMsg());  // 打印消息内容
            // 发送消息并接收响应
            BDFKIMessage res = (BDFKIMessage) socketBeiDouNet.sendMessage(msg);
            // 打印响应信息
            System.out.println(res == null ? "N" : (res.getResult() + ":" + res.getFailResult()));
            Thread.sleep(55000);  // 线程休眠55秒
        }
    }

}
